from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from fastapi.responses import JSONResponse
from models.userinfo import UserLogin, User, UserResponse, UserCreate
from plugins.mysql.database import get_db
from passlib.context import CryptContext
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
import jwt
from datetime import datetime, timedelta
import re

router = APIRouter()

# 定义密码加密上下文
pwd_context = CryptContext(
    schemes=["Argon2"], # 较新的算法，抵御定制硬件破解攻击
    bcrypt__rounds=12,  # 增加成本因子，提高加密强度
    deprecated="auto"
)

# OAuth2 密码流
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
ACCESS_TOKEN_EXPIRE_MINUTES = 1
SECRET_KEY = "f5750dfacbdf0e436d86b8f724a16f9eb745b68d8b2a12bea50874c36a21c979"
ALGORITHM = "HS256"

# 创建用户的 API 路由
@router.post("/user/login/", tags=["login"])
def login_user(login_data: UserLogin, db: Session = Depends(get_db)):
    existing_user = db.query(User).filter(User.email == login_data.email).first()
    if existing_user is None:
        return JSONResponse(status_code=200, content={
            "code": 400,
            "message": "Invalid email or password"
        })

    # 验证加密密码
    if not pwd_context.verify(login_data.password, existing_user.password):
        return JSONResponse(status_code=200, content={
            "code": 400,
            "message": "Invalid email or password"
        })

    if existing_user:
        access_token = create_access_token(
            data={
                "sub": existing_user.user_id,
                "email": existing_user.email,
                "exp": datetime.utcnow() + timedelta(minutes=5)  # Token 30 分钟后过期
            }
        )

        return JSONResponse(content={
            "code": 200,
            "user_id": existing_user.user_id,
            "email": existing_user.email,
            "password": existing_user.password,
            "access_token": access_token,
        },
            status_code=200
        )
    return JSONResponse(status_code=200, content={
        "code": 400,
        "message": "Account is error"
    })


# 生成访问令牌
def create_access_token(data: dict):
    encoded_jwt = jwt.encode(data, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


@router.post("/user/register/", response_model=UserResponse, tags=["add user"])
def create_user(user: UserCreate, db: Session = Depends(get_db)):
    if validate_email(user.email) is False:
        return JSONResponse(status_code=403, content={
            "code": 403,
            "message": "Email format verification error"
        })
    if validate_password(user.password) is False:
        return JSONResponse(status_code=403, content={
            "code": 403,
            "message": "Password format verification error"
        })
    existing_user = db.query(User).filter(User.email == user.email).first()
    if existing_user:
        return JSONResponse(status_code=200, content={
            "code": 400,
            "message": "Email already registered"
        })

    # 对密码进行加密
    hashed_password = pwd_context.hash(user.password)
    print(hashed_password)
    db_user = User(
        email=user.email,
        password=hashed_password,
    )
    db.add(db_user)
    db.commit()
    db.refresh(db_user)

    create_data = db.query(User).filter(User.email == user.email).first()
    return JSONResponse(status_code=200, content={
            "code": 200,
            "user_id": create_data.user_id,
            "email": create_data.email,
            "password": create_data.password,
            "message": "Account created successfully!"
        })


def validate_email(email):
    # 定义邮箱的正则表达式
    pattern = r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$'
    # 使用 re.match 方法进行匹配
    if re.match(pattern, email):
        return True
    else:
        return False


def validate_password(password):
    # 至少包含一个数字
    if not re.search(r'\d', password):
        return False
    # 至少包含一个特殊字符
    if not re.search(r'[!@#$%^&*()_+\-=\[\]{};:\\|,.<>\/?]', password):
        return False
    # 至少包含一个大写字母
    if not re.search(r'[A-Z]', password):
        return False
    # 至少包含一个小写字母
    if not re.search(r'[a-z]', password):
        return False
    return True


@router.post("/user/token/", tags=["token"])
async def token_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        print(payload)
        userID: int = payload.get("sub") # 获取user id
        if userID is None:
            raise credentials_exception
        Res_ID = db.query(User).filter(User.user_id == userID).first()
        if Res_ID is None:
            raise HTTPException(status_code=404, detail="User not found")
        raise HTTPException(status_code=200, detail="Certification successful")

    except jwt.PyJWTError:
        raise credentials_exception


